
/****************************************************************************/
/*Copyright (c) 2011, Florent DEVILLE.                                      */
/*All rights reserved.                                                      */
/*                                                                          */
/*Redistribution and use in source and binary forms, with or without        */
/*modification, are permitted provided that the following conditions        */
/*are met:                                                                  */
/*                                                                          */
/* - Redistributions of source code must retain the above copyright         */
/*notice, this list of conditions and the following disclaimer.             */
/* - Redistributions in binary form must reproduce the above                */
/*copyright notice, this list of conditions and the following               */
/*disclaimer in the documentation and/or other materials provided           */
/*with the distribution.                                                    */
/* - The names of its contributors cannot be used to endorse or promote     */
/*products derived from this software without specific prior written        */
/*permission.                                                               */
/* - The source code cannot be used for commercial purposes without         */ 
/*its contributors' permission.                                             */
/*                                                                          */
/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       */
/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         */
/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS         */
/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE            */
/*COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,       */
/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,      */
/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;          */
/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER          */
/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT        */
/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN         */
/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           */
/*POSSIBILITY OF SUCH DAMAGE.                                               */
/****************************************************************************/

#pragma once

#include "RTTypes.h"

namespace RT
{
	//forward declaration
	class RTVector3f;

	/*Represent a 4x4 matrix*/
	class RTMatrix44
	{
	public:

		//array representing the matrix. It's row major : m_array[ROW][COLUMN]
		F32 m_array[4][4];

	public:
		/*Default constructor*/
		RTMatrix44();

		/*Destructor*/
		~RTMatrix44();

		/*Display in std out*/
		void display()const;

		/*Set the matrix to the identity*/
		void identity();

		/*Calculate the inverse matrix*/
		RTMatrix44 inverse() const;

		/*addition*/
		RTMatrix44 operator+(const RTMatrix44& m)const;

		/*substraction*/
		RTMatrix44 operator-(const RTMatrix44& m)const;

		/*multiplication*/
		RTMatrix44 operator*(const RTMatrix44& m)const;

		/*Multiplication with a vector*/
		RTVector3f operator*(const RTVector3f& v)const;

		/*add and assign*/
		void operator+=(const RTMatrix44& m);

		/*sub and assign*/
		void operator-=(const RTMatrix44& m);

		/*assign*/
		void operator=(const RTMatrix44& m)const;

		/*create a translation matrix*/
		void createTranslation(F32 x, F32 y , F32 z);

		/*Create a translation matrix from a vector*/
		void createTranslation(const RTVector3f& v);

		/*create a rotation matrix around X axis*/
		void createRotationX(F32 radiusAngle);

		/*create a rotation matrix around Y axis*/
		void createRotationY(F32 radiusAngle);

		/*create a rotation matrix around Z axis*/
		void createRotationZ(F32 radiusAngle);

		/*create a rotation matrix a specific axis*/
		void createRotation(const RTVector3f& axis, F32 angle);

		/*create a non uniform scale matrix*/
		void createScale(const RTVector3f& s);

		/*create a uniform scale matrix*/
		void createScale(F32 s);

		//convert the matrix to an opengl matrix (column major)
		void getOpenGLMatrix(F64* matrix);

		//calculate frenet matrix
		void createFrenet(const RTVector3f& position, const RTVector3f& direction, const RTVector3f& up);

		//build a matrix using three vectors as columns
		void buildColumn(const RTVector3f& c1, const RTVector3f& c2, const RTVector3f& c3);

		//calculate the determinant
		F32 det()const;
	};

}
